package com.zg.autoflow.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import cn.smallbun.screw.core.util.CollectionUtils;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.xn.fastxls.*;
import com.zg.autoflow.dao.mapper.AutoFlowBusinessMapper;
import com.zg.autoflow.enm.FlowContants;
import com.zg.autoflow.req.AutoflowMainAddReq;
import com.zg.autoflow.req.AutoflowMainIdReq;
import com.zg.autoflow.req.AutoflowMainPageReq;
import com.zg.autoflow.service.AutoflowMainService;
import com.zg.autoflow.service.SettleWorkflowService;
import com.zg.autoflow.vo.*;
import com.zg.common.core.A;
import com.zg.common.core.dao.BaseEntity;
import com.zg.common.core.dao.auth.AuthOrg;
import com.zg.common.core.dao.auth.AuthOrgDao;
import com.zg.common.core.dao.auth.AuthUser;
import com.zg.common.core.dao.auth.AuthUserDao;
import com.zg.common.core.dao.autoflow.dao.*;
import com.zg.common.core.dao.autoflow.entity.*;
import com.zg.common.core.dao.autoform.DiyView;
import com.zg.common.core.dao.autoform.DiyViewDao;
import com.zg.common.core.exception.BusinessException;
import com.zg.common.dds.DbTypeUtil;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.InputStream;
import java.util.*;
import java.util.stream.Collectors;

/**
* @author zg
*/
@Service
@RequiredArgsConstructor
public class AutoflowMainServiceImpl implements AutoflowMainService {

    private final AutoflowMainDao autoflowMainDao;
    private final AutoflowStepDao autoflowStepDao;
    private final AutoflowStepPersonDao autoflowStepPersonDao;
    private final AutoFlowBusinessMapper autoFlowBusinessMapper;
    private final AutoflowStepSubDao autoflowStepSubDao;
    private final AutoflowStepSubPersonDao autoflowStepSubPersonDao;
    private final AutoflowSubDao autoflowSubDao;
    private final SettleWorkflowService settleWorkflowService;
    private final AuthOrgDao authOrgDao;
    private final AuthUserDao authUserDao;
    private final DiyViewDao diyViewDao;
    private final AutoflowStepFormDao autoflowStepFormDao;
    private final DbTypeUtil dbTypeUtil;

    @Value("${tempFilePath}")
    private String tempFilePath; //模板文件的路径

    void checkAdd(AutoflowMainAddReq param) {
        String name = param.getName();
        if (autoflowMainDao.exists(new LambdaQueryWrapper<AutoflowMain>().eq(AutoflowMain::getName,name).eq(BaseEntity::getIsDel,false))){
            BusinessException.happen("流程名称重复，请修改！您可以在名称后加上（机构名称）");
        }

    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public AutoflowMain add(AutoflowMainAddReq param) {
        //校验逻辑
        checkAdd(param);
        //创建对象
        AutoflowMain obj = new AutoflowMain();
        //属性处理
        BeanUtil.copyProperties(param, obj);
        obj.setIsUse("N");
        obj.setState("1");
        obj.setVersion(1);
        //查询机构序列code
        String orgSeqCode = "";
//        Map<String, String> orgMap = new HashMap<>();
//        orgMap.put("ID", ORG_ID.toString());
//        List orgList = backNormalMapper.getOrgQueryList(orgMap);
//        if (orgList.size() > 0) {
//            orgMap = (Map) orgList.get(0);
//            orgSeqCode = orgMap.get("ORG_SEQ_CODE");
//        }
        String floeSeqCode = "";
        String type = param.getType();
        if (org.apache.commons.lang.StringUtils.isNotEmpty(type) && org.apache.commons.lang.StringUtils.isNotEmpty(orgSeqCode)) {
            floeSeqCode = "WFA_" + type + "_" + orgSeqCode + "_";
        } else {
            //错误数据情况 增加默认
            floeSeqCode = "WFA_"+type+"_JM_";
        }
        //生成流程编码
        String flowCode = generateFlowCodes(floeSeqCode);
        obj.setCode(flowCode);
        obj.setState("1");
        StringBuffer strBuff = new StringBuffer();
        obj.setSearchStr(strBuff.toString());
        //保存对象
        autoflowMainDao.save(obj);
        return obj;
    }

    /**
     * 生成流程编码
     *
     * @param
     * @return
     */
    private synchronized String generateFlowCodes(String FLOW_CODE) {
        Long count = autoflowMainDao.getBaseMapper().selectCount(new LambdaQueryWrapper<>());
        return FLOW_CODE + String.format("%05d", count+1);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void del(@RequestParam("ids") List<Long> idList) {
        autoflowMainDao.removeBatchByIds(idList);
    }

    void checkUpdate(AutoflowMainUpdateVo param) {
        //BusinessException.happen("这里是提示信息");
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public AutoflowMain update(AutoflowMainUpdateVo param) {
        //查询对象
        AutoflowMain oldObj = autoflowMainDao.getById(param.getId());
        A.isInDatabase(oldObj, "要更新的对象");
        //校验逻辑
        checkUpdate(param);
        //属性处理
        BeanUtil.copyProperties(param, oldObj);
        StringBuffer strBuff = new StringBuffer();
        oldObj.setSearchStr(strBuff.toString());
        //更新对象
        autoflowMainDao.updateById(oldObj);
        return oldObj;
    }

    @Override
    public IPage<AutoflowMainPageVo> page(Page<AutoflowMainPageVo> objectPage, AutoflowMainPageReq autoflowMainPageReq) {
        String dbType =null;
        if ( dbTypeUtil.isMysql()){
            dbType="0";
        }else if (dbTypeUtil.isOracle()){
            dbType="1";
        }
        autoflowMainPageReq.setDbType(dbType);
        return autoFlowBusinessMapper.page(objectPage,autoflowMainPageReq);
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public void insetOrUpdateAutoFlow(String ID, MultipartFile file) throws Exception {
        InputStream inputStream = file.getInputStream();
        XSSFWorkbook workbook = new XSSFWorkbook(inputStream);
        FlowData flowData = new ImportExcelReader().analyseFlow(workbook);

        LambdaQueryWrapper<AuthOrg> queryOrgWrapper = new LambdaQueryWrapper<>();
//        有:说明确定ID
        if (flowData.采集机构.contains(":")) {
            String[] split = flowData.采集机构.split(":");
            queryOrgWrapper.eq(AuthOrg::getName, split[0]);
            queryOrgWrapper.eq(AuthOrg::getId, split[1]);
        } else {
            queryOrgWrapper.eq(AuthOrg::getName, flowData.采集机构);
        }
        AuthOrg sysOrg = authOrgDao.getOne(queryOrgWrapper);
        if (sysOrg == null) {
            throw new InfoException("采集机构名称错误 请核实");
        }
        // 除客户选市场环节，其他环节限制使用主体
        if (checkFormOfLimitZt(flowData)) {
            throw new InfoException("除根据合同选市场环节，限制使用主体选项!");
        }

        String NEXT_FLOW_CODE = "";
        String NEXT_AUTH_ORG = "";
        String NEXT_AUTH_USER = "";
        Long ORG_ID = sysOrg.getId();
        String TYPE = flowData.流程类型;
        //如果有后续启动
        if (flowData.后续流程.length() > 0) {
            LambdaQueryWrapper<AutoflowMain> queryWrapper1 = new LambdaQueryWrapper<>();
            queryWrapper1.eq(AutoflowMain::getName, flowData.后续流程);
            AutoflowMain houxu = autoflowMainDao.getOne(queryWrapper1);
            if (houxu == null) {
                throw new InfoException("后续流程没有找到 请确认名字");
            }

            LambdaQueryWrapper<AuthOrg> queryWrapper3 = new LambdaQueryWrapper<>();
            //有:说明确定ID
            if (flowData.后续启动组织.contains(":")) {
                String[] split = flowData.后续启动组织.split(":");
                queryWrapper3.eq(AuthOrg::getName, split[0]);
                queryWrapper3.eq(AuthOrg::getId, split[1]);
            } else {
                queryWrapper3.eq(AuthOrg::getName, flowData.后续启动组织);
            }
            AuthOrg houxuo = authOrgDao.getOne(queryWrapper3);
            if (houxuo == null) {
                throw new InfoException("后续流程启动机构没有找到 请确认名字");
            }
            String nextFlowPerson = flowData.后续启动人;
            if (StrUtil.isNotEmpty(nextFlowPerson)){
                String[] split = nextFlowPerson.split(":");
                if (split.length==2){
                    Wrapper<AuthUser> userWrapper = new LambdaQueryWrapper<AuthUser>().eq(AuthUser::getName, split[0]).eq(AuthUser::getUsername, split[1]);
                    AuthUser houxuqidongren = authUserDao.getOne(userWrapper);
                    if (ObjectUtils.isEmpty(houxuqidongren)){
                        throw new InfoException("人员信息未找到：" + flowData.后续启动人);
                    }else {
                        NEXT_FLOW_CODE = houxu.getCode();
                        NEXT_AUTH_USER = houxuqidongren.getId().toString();
                        NEXT_AUTH_ORG = houxuqidongren.getOrgId()+"";
                    }
                }
            }
        }

        String NAME = flowData.流程名称;
        if (!NEXT_FLOW_CODE.equals("")) {
            if (NEXT_AUTH_USER.equals("")) {
                throw new InfoException("选择后续组织机构后请选择后续流程启动人");
            }
            if (NEXT_AUTH_ORG.equals("")) {
                throw new InfoException("选择后续流程后请选择后续启动组织结构和启动人");
            }
        }

        //验证名字
        LambdaQueryWrapper<AutoflowMain> queryWrapper1 = new LambdaQueryWrapper<>();
        if (org.apache.commons.lang.StringUtils.isNotEmpty(ID)) {
            queryWrapper1.ne(AutoflowMain::getId, ID);
        }
        queryWrapper1.eq(AutoflowMain::getName, NAME);
        Long count = autoflowMainDao.count(queryWrapper1);
        if (count > 0) {
            throw new InfoException("流程名称重复，请修改！您可以在名称后加上“（机构名称）");
        }
        AutoflowMain flow;
        //判断id是否为空
        if (org.apache.commons.lang.StringUtils.isNotEmpty(ID)) {
            flow = autoflowMainDao.getById(ID);

            //导入流程时校验是否有绑定环节，导入流程时校验是否有绑定环节开关，建议关闭时人工校验是否有绑定环节，重新导入的流程是否符合绑定环节的要求（连续环节，处理人相同），Y-开启，N关闭
//            LambdaQueryWrapper<SysCommonConfig> sysCommonConfigLambdaQueryWrapper = new LambdaQueryWrapper<>();
//            sysCommonConfigLambdaQueryWrapper.eq(SysCommonConfig::getConfigKey, "IMPORT_FLOW_IS_CHECK_BIND_STEP");
//            SysCommonConfig sysCommonConfig = sysCommonConfigMapper.selectOne(sysCommonConfigLambdaQueryWrapper);
//            if (ObjectUtils.isEmpty(sysCommonConfig) || "Y".equals(sysCommonConfig.getConfigValue())) {
//                List<SettleWorkflowStepBind> settleWorkflowStepBinds = settleWorkflowStepBindService.selectBindStepByFlowCode(flow.getCode());
//                if (ObjectUtils.isNotEmpty(settleWorkflowStepBinds)) {
//                    throw new InfoException("导入失败，流程存在绑定环节，请解绑后导入！");
//                }
//            }
            //更新数据
            flow.setType(TYPE);
            flow.setName(NAME);
            flow.setOrgId(ORG_ID);
            flow.setNextFlowCode(NEXT_FLOW_CODE);
            flow.setNextAuthOrg(NEXT_AUTH_ORG);
            flow.setNextAuthUser(NEXT_AUTH_USER);
            flow.setCanStart(flowData.是否可以直接发起);
            autoflowMainDao.updateById(flow);
            importProcessLink(flow.getId(), flowData);
        } else {
//            //查询机构序列code
//            String orgSeqCode = "";
//            Map<String, String> orgMap = new HashMap<>();
//            orgMap.put("ID", ORG_ID.toString());
//            List orgList = backNormalMapper.getOrgQueryList(orgMap);
//            if (orgList.size() > 0) {
//                orgMap = (Map) orgList.get(0);
//                orgSeqCode = orgMap.get("ORG_SEQ_CODE");
//            }
//            String floeSeqCode = "";
//            if (org.apache.commons.lang.StringUtils.isNotEmpty(TYPE) && org.apache.commons.lang.StringUtils.isNotEmpty(orgSeqCode)) {
//                floeSeqCode = "WFA_" + TYPE + "_" + orgSeqCode + "_";
//            } else {
//                //错误数据情况 增加默认
//                floeSeqCode = "WFA_RY_JM_";
//            }
//            //生成流程编码
//            String flowCode = generateFlowCodes(floeSeqCode);
            String floeSeqCode = "WFA_RY_JM_";
            //生成流程编码
            String flowCode = generateFlowCodes(floeSeqCode);
            flow = new AutoflowMain();
            flow.setType(TYPE);
            flow.setName(NAME);
            flow.setOrgId(ORG_ID);
            flow.setNextFlowCode(NEXT_FLOW_CODE);
            flow.setNextAuthOrg(NEXT_AUTH_ORG);
            flow.setNextAuthUser(NEXT_AUTH_USER);
            flow.setCode(flowCode);
            flow.setCanStart(flowData.是否可以直接发起);
            flow.setIsUse("N");
            flow.setState("1");
            autoflowMainDao.save(flow);
            importProcessLink(flow.getId(), flowData);
        }


        //清空相应的redis
//        autoflowMainDao.clearRedis(flow.getId());
//        autoflowMainDao.clearRedis(flow.getId());

        //子流程
        List<SubFlow> subFlows = flowData.SubFlows;
        String code = flow.getCode();
        LambdaQueryWrapper<AutoflowSub> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(AutoflowSub::getFlowCode,code);
        //清空子流程
        autoflowSubDao.remove(queryWrapper);
        LambdaQueryWrapper<AutoflowStepSub> autoflowStepSubLambdaQueryWrapper = new LambdaQueryWrapper<>();
        autoflowStepSubLambdaQueryWrapper.eq(AutoflowStepSub::getFlowCode,code);
        autoflowStepSubDao.remove(autoflowStepSubLambdaQueryWrapper);
        LambdaQueryWrapper<AutoflowStepSubPerson> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(AutoflowStepSubPerson::getFlowCode,code);
        autoflowStepSubPersonDao.remove(wrapper);

        if (subFlows.size() == 0) {
            return;
        }
        for (SubFlow subFlow : subFlows) {
            AutoflowSub autoflowSub = new AutoflowSub();
            autoflowSub.setName(subFlow.getNAME());
            autoflowSub.setField(subFlow.getFIELD());
            autoflowSub.setFieldValue(subFlow.getFIELD_VALUE());
            autoflowSub.setField2(subFlow.getFIELD2());
            autoflowSub.setField2Value(subFlow.getFIELD2_VALUE());
            autoflowSub.setFlowCode(flow.getCode());
            autoflowSubDao.save(autoflowSub);
            List<SubFlowStep> subFlowSteps = subFlow.SubFlowSteps;
            //查询人员信息
            Set<String> usernames = new HashSet<>();
            for (SubFlowStep step : subFlowSteps) {
                if (step.STEP_NO.equals(FlowContants.StepCode.STEP_OVER)) {
                    continue;
                }
                String step_hander = step.getSTEP_HANDER();
                if (org.apache.commons.lang.StringUtils.isBlank(step_hander)) {
                    throw new InfoException("子环节处理人不能为空  子流程：" + autoflowSub.getName() + " 环节 " + step.getSTEP_NAME());
                }
                String[] split = step_hander.split(",");
                for (String name : split) {
                    usernames.add(name);
                }
            }
            Map<String, AuthUser> userInfoByNamesMap = getUserInfoByNameAccounts(usernames);
            //所有的子环节
            List<AutoflowStepSub> autoflowStepSubs = new ArrayList<>();
            //所有的处理人
            List<AutoflowStepSubPerson> autoflowStepSubPersonList = new ArrayList<>();

            for (SubFlowStep subFlowStep : subFlowSteps) {
                AutoflowStepSub autoflowStepSub = new AutoflowStepSub();
                autoflowStepSub.setFlowCode(flow.getCode());
                autoflowStepSub.setStepNo(subFlowStep.getSTEP_NO());
                autoflowStepSub.setStepName(subFlowStep.getSTEP_NAME());
                autoflowStepSub.setNextStepId(subFlowStep.getNEXT_STEP_ID());
                autoflowStepSub.setSubFlowId(autoflowSub.getId());
                autoflowStepSubs.add(autoflowStepSub);
                String step_hander = subFlowStep.getSTEP_HANDER();

                String[] split = step_hander.split(",");
                for (String name : split) {
                    AuthUser user = userInfoByNamesMap.get(name);
                    AutoflowStepSubPerson autoflowStepSubPerson = new AutoflowStepSubPerson();
                    autoflowStepSubPerson.setFlowCode(flow.getCode());
                    autoflowStepSubPerson.setStepCode(subFlowStep.getSTEP_NO());
                    autoflowStepSubPerson.setSubFlowId(autoflowSub.getId());
                    autoflowStepSubPerson.setStepHandler(user.getId());
                    autoflowStepSubPerson.setStepHandlerOrg(user.getOrgId()+"");
                    autoflowStepSubPersonList.add(autoflowStepSubPerson);
                }
            }
            autoflowStepSubDao.saveBatch(autoflowStepSubs);
            autoflowStepSubPersonDao.saveBatch(autoflowStepSubPersonList);

        }

    }

    @Override
    public void syncAutoFlow(Long flowId) {
        //查询流程信息
        AutoflowMain autoflowMain = autoflowMainDao.getById(flowId);
        if (autoflowMain == null) {
            throw new InfoException("未查询到流程信息！");
        }
        //查询流程环节信息
        List<AutoflowStep> stepList = autoflowStepDao.list(new LambdaQueryWrapper<AutoflowStep>().eq(AutoflowStep::getFlowId,flowId));
        if (stepList == null) {
            throw new InfoException("未查询到流程的环节信息！");
        }
        String checkFlowIsOk = this.checkFlowIsOk(stepList);
        if(org.apache.commons.lang3.StringUtils.isNotEmpty(checkFlowIsOk)){
            throw new InfoException(checkFlowIsOk+"请检查后重新发布！");
        }
        if(!FlowContants.CollectState.PROCESSPASS.equals(autoflowMain.getState()) && !FlowContants.CollectState.PUBLISHED.equals(autoflowMain.getState())){
            throw new InfoException("必须是审核通过才可以使用此功能！");
        }
        //判断后置流程是否有效
        if(org.apache.commons.lang3.StringUtils.isNotBlank(autoflowMain.getNextFlowCode())){
            AutoflowMain byCode = autoflowMainDao.getOne(new LambdaQueryWrapper<AutoflowMain>().eq(AutoflowMain::getCode,autoflowMain.getNextFlowCode()));
            if (byCode == null) {
                throw new InfoException("未查询到后置流程的流程信息！");
            }
            //判断后置流程的采集状态
            if(!FlowContants.CollectState.PROCESSPASS.equals(byCode.getState()) && !FlowContants.CollectState.PUBLISHED.equals(byCode.getState())){
                throw new InfoException("后置流程未审核通过，请先审核后置流程！");
            }
        }
        settleWorkflowService.syncAutoFlow(autoflowMain);
    }

    @Override
    public String agreeAutoFlow(AutoflowMainIdReq param) {
        String flowId =param.getFlowId()+"";
        String r = checkFlowIsOk(flowId);
        if(!r.equals("")){return r;}
        AutoflowMain autoflowMain = autoflowMainDao.getById(flowId);
        List<String> stateList = Arrays.asList("1", "2");
        if(!stateList.contains(autoflowMain.getState())) {
            return "必须是审核中才可以使用此功能！";
        }
        autoflowMain.setState("3");
        autoflowMainDao.updateById(autoflowMain);
        return "审核通过";
    }

    @Override
    public String unagreeAutoFlow(AutoflowMainIdReq param) {
        AutoflowMain autoflowMain = autoflowMainDao.getById(param.getFlowId());
        List<String> stateList = Arrays.asList("1", "2");
        if(!stateList.contains(autoflowMain.getState())) {
            return "必须是审核中才可以使用此功能！";
        }
        autoflowMain.setState("4");
        autoflowMainDao.updateById(autoflowMain);
        return "审核不通过";
    }

    @Override
    public void exportFlowExcel(HttpServletResponse response, Long flowId) throws Exception{
        AutoflowMain byId = autoflowMainDao.getById(flowId);
        XSSFWorkbook workbook = createProcessLinkWorkbook(flowId+"");
        // 告诉浏览器用什么软件可以打开此文件
        response.setContentType("application/force-download");// 设置强制下载不打开
        response.addHeader("Content-Disposition", "attachment;fileName=" + new String(byId.getName().getBytes("UTF-8"), "ISO-8859-1") + ".xlsx");// 设置文件名
        workbook.write(response.getOutputStream());
        workbook.close();
    }

    //检查流程是否ok
    public String checkFlowIsOk(String flowId) {
        List<AutoflowStep> stepList = autoflowStepDao.list(new LambdaQueryWrapper<AutoflowStep>().eq(AutoflowStep::getFlowId,flowId));
        if (stepList == null) {
            throw new InfoException("未查询到流程的环节信息！");
        }
        String checkFlowIsOk = checkFlowIsOk(stepList);
        return checkFlowIsOk;
    }

    public String checkFlowIsOk(List<AutoflowStep> stepList){
        boolean hasStartPoint = false;
        boolean hasEndPoint = false;
        boolean isEnd = false;
        StringBuffer checkMessage = new StringBuffer();

        Map<String,Set<String>> stepmap = new HashMap<>();

        Set<String> allnext = new HashSet<>();
        for (AutoflowStep step:stepList ) {
            if(org.apache.commons.lang3.StringUtils.isBlank(step.getNextStepId())) {
                checkMessage.append(step.getStepNo() + "节点的节点的下一环节为空;");
            }
            String[] split = step.getNextStepId().split(",");
            Set<String> next = new HashSet<>();
            for (String s:split  ) {
                next.add(s);
                allnext.add(s);
            }
            stepmap.put(step.getStepNo(),next);

            //验证表单
            if(!step.getStepNo().equals(FlowContants.StepCode.STEP_OVER)) {
                //检查是否设置表单
                Long stepId = step.getId();
                List<AutoflowStepForm> formList = autoflowStepFormDao.list(new LambdaQueryWrapper<AutoflowStepForm>().eq(AutoflowStepForm::getStepId, stepId));
                if(CollectionUtil.isEmpty(formList)){
                    checkMessage.append(step.getStepNo()+"环节未设置表单!");
                }
                QueryWrapper<AutoflowStepPerson> queryWrapper = new QueryWrapper<>();
                queryWrapper.lambda().eq(AutoflowStepPerson::getStepId, step.getId());
                //处理人
                List<AutoflowStepPerson> stepHandlerByStepId = autoflowStepPersonDao.list(queryWrapper);
                if(stepHandlerByStepId.size()==0){
                    checkMessage.append(step.getStepNo()+"环节未设置处理人!");
                }
            }
        }
        if(! stepmap.containsKey(FlowContants.StepCode.STEP_START))
        {
            checkMessage.append("流程没有启动节点;");
        }
        if(! stepmap.containsKey(FlowContants.StepCode.STEP_OVER))
        {
            checkMessage.append("流程没有结束节点;");
        }
        //必须都有
        for (String No:allnext   ) {
            if(! stepmap.containsKey(No)) {
                checkMessage.append("节点缺失"+No +";");
            }
        }
        if(checkMessage.length()>0) {
            return  checkMessage.toString();
        }
        return  checkMessage.toString();
    }

    private Boolean checkFormOfLimitZt(FlowData flowData) {
        if (CollectionUtils.isEmpty(flowData.liuchnegarray)) {
            return false;
        }
        for (FlowStepInfo info : flowData.liuchnegarray) {
            String selectHandlerMode = info.getSELECT_HANDLER_MODE();
            String zt = info.getZT();
            if (ObjectUtils.isNotEmpty(selectHandlerMode) && ObjectUtils.isNotEmpty(zt)) {
                if ("根据合同选市场".equals(selectHandlerMode)) {
                    continue;
                } else {
                    return true;
                }
            } else if (ObjectUtils.isNotEmpty(zt)) {
                return true;
            }
        }
        return false;
    }

    @Transactional
    public void importProcessLink(Long flowId, FlowData flowData) throws Exception{
        if (flowId == null) {
            throw new InfoException("导入需要的所属流程flowId缺失，请传入后再导入");
        }
        //校验不能重复导入 如果二次导入就把之前导入的数据删了 然后重新插入
        List<AutoflowStep> autoFlowStepList = autoflowStepDao.list(new LambdaQueryWrapper<AutoflowStep>()
                .eq(AutoflowStep::getFlowId,flowId).eq(BaseEntity::getIsDel,false));
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("targetId", flowId);//目标id
        Set<Long> objectAttributeSet =autoFlowStepList.stream().map(AutoflowStep::getId).collect(Collectors.toSet());
        if (autoFlowStepList.size() > 0) {
            jsonObject.put("operType", "1");//修改类型
            jsonObject.put("histContent", autoFlowStepList);//历史信息
            //删除环节
            LambdaQueryWrapper<AutoflowStep> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(AutoflowStep::getFlowId, flowId);
            autoflowStepDao.remove(queryWrapper);
            //删除处理人
            LambdaQueryWrapper<AutoflowStepPerson> queryWrapper1 = new LambdaQueryWrapper<>();
            queryWrapper1.in(AutoflowStepPerson::getStepId, objectAttributeSet);
            autoflowStepPersonDao.remove(queryWrapper1);
        } else {
            jsonObject.put("operType", "0");//新增类型
        }
        //所有流程环节的配置信息
        List<FlowStepInfo> flowInfoStepArray = flowData.liuchnegarray;
        //先拿到所有环节编号
        Map<String, FlowStepInfo> FlowStepInfoMap = flowInfoStepArray.stream().collect(Collectors.toMap(FlowStepInfo::getSTEP_NO,line->line));
        //环节处理人
        Set<String> HANDLERNames = new HashSet<>();
        Set<String> RoleNames = new HashSet<>();
        Set<String> addAllNames = new HashSet<>();
        for (FlowStepInfo info : flowData.liuchnegarray) {
            //去除中文逗号
            info.STEP_HANDLER = info.STEP_HANDLER.replace("，", ",");
            info.NEXT_STEPNO = info.NEXT_STEPNO.replace("，", ",");
            if (info.STEP_HANDLER.length() > 0) {
                //集中用户
                String[] HANDLERS = info.STEP_HANDLER.split(",");
                for (String name : HANDLERS) {
                    if (name.split(":")[0].equals("role_name")) {
                        RoleNames.add(name);
                    } else {
                        HANDLERNames.add(name);
                    }
                }
            }
        }
        if (RoleNames != null && RoleNames.size() > 0) {
//            Set<String> selectByNames = handlerRoleManageService.selectByNames(RoleNames);
//            if (selectByNames != null && selectByNames.size() > 0) {
//                addAllNames.addAll(selectByNames);
//            }
        }
        addAllNames.addAll(HANDLERNames);
        //查询关联的所有用户
        Map<String, AuthUser> userMap = getUserInfoByNameAccounts(addAllNames);
        //查询表单
        Set<String> formnames = flowInfoStepArray.stream().map(FlowStepInfo::getSTEP_FORM).collect(Collectors.toSet());
        LambdaQueryWrapper<DiyView> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.in(DiyView::getName, formnames);
        List<DiyView> list1 = diyViewDao.list(queryWrapper);
        Map<String, DiyView> stringAutoformMaimMap =list1.stream().collect(Collectors.toMap(DiyView::getName,line->line));
        //流程环节
        ArrayList<AutoflowStep> stepsList = new ArrayList();
        for (int i = 0; i < flowInfoStepArray.size(); i++) {
            FlowStepInfo info = flowInfoStepArray.get(i);
            //去除中文逗号
            String nodeNo = info.STEP_NO;
            if (!FlowStepInfoMap.containsKey(nodeNo)) {
                //后续环节不在设定环节中，返回提示
                throw new InfoException("该环节的后续节点中，有不属于该流程的节点");
            }
            //获取环节表的id
            //去除数据库环节表的自增，改成后端代码传入
            AutoflowStep autoLowStep = new AutoflowStep();
            autoLowStep.setSeq(i + 1l);
            //环节类型
            autoLowStep.setStepType("1");
            //处理下一节点，可能有多个节点名称
            autoLowStep.setNextStepId(info.NEXT_STEPNO);
            autoLowStep.setFlowId(flowId);
            autoLowStep.setStepNo(info.STEP_NO);
            autoLowStep.setStepName(info.NODE_NAME);
            autoLowStep.setBillStep(billTypeToNumber(info.BILL_STEP));
            autoLowStep.setIsEdit(YnTo01(info.IS_EDIT));
            autoLowStep.setIsReturn(YnTo01(info.IS_RETURN));
            autoLowStep.setIsReturned(YnTo01(info.IS_RETURNED));
            autoLowStep.setIsSeal(YnTo01(info.IS_SEAL));
            //单签会签
            autoLowStep.setApproveType(ImportExcelReader.APPROVE_NAME_TO_TYPE(info.APPROVE_TYPE));
            //选人模式
            autoLowStep.setSelectHandlerMode(info.SELECT_HANDLER_MODE);
            //是否有短信
            autoLowStep.setShortMessage(YnTo01(info.SHORT_MESSAGE));
            //短信模板类型
            autoLowStep.setShortMessageType(info.SHORT_MESSAGE_TYPE);
            autoLowStep.setStepParameter(info.STEP_PARAMETER);
            //盖章数据
            //是否某主体的结束节点
            autoLowStep.setIsStepEnd("0");
            //流程环节归属子公司还是销售主体 2子公司 3 销售主体
            autoLowStep.setStepFlag("0");

            //退回是否需要审批
            autoLowStep.setIsBackApproval(YnTo01(info.IS_BACK_APPROVAL));
            autoLowStep.setFlowStepType(info.getFLOW_STEP_TYPE());
            autoLowStep.setZt(info.getZT());
            DiyView diyView = stringAutoformMaimMap.get(info.getSTEP_FORM());
            if (diyView != null) {
                autoLowStep.setStepFormId(diyView.getId());
            }
            stepsList.add(autoLowStep);
        }

        //保存环节
        autoflowStepDao.saveBatch(stepsList);
        jsonObject.put("content", stepsList);//修改后的内容
        jsonObject.put("operTarget", "1");//流程目标
//        jsonObject.put("targetName", flowData.流程名称);//目标名称
//        changeRecordService.addChangeRecord(jsonObject);//新增更改记录
        List<AutoflowStepPerson> peosons = new ArrayList<>();
        for (AutoflowStep step : stepsList) {
            //处理人、组织编号拼接，STEP_HANDLER对应sys_user的user_name,可能设计多个处理人

            FlowStepInfo flowStepInfo = FlowStepInfoMap.get(step.getStepNo());

            String step_handler = flowStepInfo.getSTEP_HANDLER();
            if (!StringUtils.isEmpty(step_handler)) {
                String[] names = step_handler.split(",");
                for (int i = 0; i < names.length; i++) {
                    String name = names[i];
                    if (name.split(":")[0].equals("role_name")) {
//                        Set<String> roleNames = handlerRoleManageService.selectByName(name);
//                        if (roleNames != null && roleNames.size() > 0) {
//                            for (String roleName : roleNames) {
//                                if (!HANDLERNames.contains(roleName)) {
//                                    AuthUser user = userMap.get(roleName);
//                                    AutoflowStepPerson p = new AutoflowStepPerson();
//                                    p.setStepHandler(user.getId());
//                                    p.setStepHandlerOrg(user.getOrgId()+"");
//                                    p.setStepId(step.getId());
//                                    peosons.add(p);
//                                }
//                            }
//                        }
                    } else {
                        AuthUser user = userMap.get(name);
                        AutoflowStepPerson p = new AutoflowStepPerson();
                        p.setStepHandler(user.getId());
                        p.setStepHandlerOrg(user.getOrgId()+"");
                        p.setStepId(step.getId());
                        peosons.add(p);
                    }
                }
            }
        }

        if (peosons.size() > 0) {
            autoflowStepPersonDao.saveBatch(peosons);
        }
    }

    private static String billTypeToNumber(String info) {
        switch (info) {
            case "非发票":
                return "0";
            case "矿点发票":
                return "1";
            case "子公司发票":
                return "2";
            case "销售主体发票":
                return "3";
            case "矿点红票":
                return "5";
            case "子公司红票":
                return "6";
            case "销售主体红票":
                return "7";
            default:
                return "4";
        }
    }
    private String YnTo01(String info) {
        return info.equals("Y") ? "1" : "0";
    }

    private XSSFWorkbook createProcessLinkWorkbook(String flowId) throws Exception {
        AutoflowMain one = autoflowMainDao.getOne(new LambdaQueryWrapper<AutoflowMain>().eq(AutoflowMain::getId, flowId));
        AuthOrg sysOrg = authOrgDao.getById(one.getOrgId());
        JSONObject oneAutoflowMainJson = (JSONObject) JSON.toJSON(one);
        oneAutoflowMainJson.put("orgName", sysOrg.getName() + ":" + sysOrg.getId());
        JSONObject nextflow = null;
        if (one.getNextFlowCode() != null && !"".equals(one.getNextFlowCode())) {
            AutoflowMain autoflowMain = autoflowMainDao.getOne(new LambdaQueryWrapper<AutoflowMain>().eq(AutoflowMain::getCode, one.getNextFlowCode()));
            AuthUser nextSysUser = authUserDao.getOne(new LambdaQueryWrapper<AuthUser>().eq(AuthUser::getId, one.getNextAuthUser()));
            AuthOrg sysOrgNext = authOrgDao.getById(nextSysUser.getOrgId());
            nextflow = new JSONObject();
            nextflow.put("flowName", autoflowMain.getName());
            nextflow.put("orgName", sysOrgNext.getName());
            nextflow.put("userName", nextSysUser.getName());
        }
        LambdaQueryWrapper<AutoflowStep> queryWrapper = new LambdaQueryWrapper<AutoflowStep>();
        queryWrapper.eq(AutoflowStep::getFlowId, flowId)
                .orderByAsc(AutoflowStep::getSeq)
                .orderByAsc(AutoflowStep::getId);
        List<AutoflowStep> autoflowSteplist = autoflowStepDao.list(queryWrapper);

        JSONArray autoflowSteplistjson = (JSONArray) JSON.toJSON(autoflowSteplist);
        for (int i = 0; i < autoflowSteplist.size(); i++) {

            AutoflowStep step = autoflowSteplist.get(i);

            DiyView byFormId = diyViewDao.getById(step.getStepFormId());
            if (byFormId != null) {
                autoflowSteplistjson.getJSONObject(i).put("stepForm", byFormId.getName());
            }
        }


        HashMap<Long, String> useridtousernamemap = new HashMap<>();
        Set<Long> stepids =autoflowSteplist.stream().map(AutoflowStep::getId).collect(Collectors.toSet());
        LambdaQueryWrapper<AutoflowStepPerson> queryWrapper5 = new LambdaQueryWrapper<>();
        queryWrapper5.in(AutoflowStepPerson::getStepId, stepids);
        List<AutoflowStepPerson> list4 = autoflowStepPersonDao.list(queryWrapper5);

        JSONArray AutoflowStepPersons = (JSONArray) JSON.toJSON(list4);

        //所有的用户
        Set<String> userids = new HashSet<>();
        for (AutoflowStepPerson p : list4) {
            userids.add(p.getStepHandler().toString());
        }
        List<AuthUser> swanEntUsers = authUserDao.listByIds(userids);

        LambdaQueryWrapper<AuthUser> queryWrapper4 = new LambdaQueryWrapper<>();
        queryWrapper4.in(AuthUser::getId, userids);
        //账户信息
        List<AuthUser> list3 = authUserDao.list(queryWrapper4);
        Map<Long, AuthUser> longSwanEntUserAccountMap =list3.stream().collect(Collectors.toMap(BaseEntity::getId,line->line));
        for (AuthUser user : swanEntUsers) {
            AuthUser swanEntUserAccount = longSwanEntUserAccountMap.get(user.getId());
            useridtousernamemap.put(user.getId(), user.getName() + ":" + swanEntUserAccount.getUsername());
        }
        //子流程
        LambdaQueryWrapper<AutoflowSub> queryWrapper1 = new LambdaQueryWrapper<>();
        queryWrapper1.eq(AutoflowSub::getFlowCode, one.getCode());
        queryWrapper1.orderBy(true, true, AutoflowSub::getId);
        List<AutoflowSub> list = autoflowSubDao.list(queryWrapper1);
        JSONArray AutoflowSubs = new JSONArray();
        JSONArray AutoflowStepSubs = new JSONArray();
        JSONArray AutoflowStepSubPersons = new JSONArray();
        if (list.size() > 0) {
            AutoflowSubs = (JSONArray) JSON.toJSON(list);
            List<Long> objectAttributeList1 =list.stream().map(AutoflowSub::getId).collect(Collectors.toList());
            LambdaQueryWrapper<AutoflowStepSub> queryWrapper2 = new LambdaQueryWrapper<>();
            queryWrapper2.in(AutoflowStepSub::getSubFlowId, objectAttributeList1);
            queryWrapper2.orderBy(true, true, AutoflowStepSub::getId);
            List<AutoflowStepSub> list1 = autoflowStepSubDao.list(queryWrapper2);
            AutoflowStepSubs = (JSONArray) JSON.toJSON(list1);

            LambdaQueryWrapper<AutoflowStepSubPerson> queryWrapper3 = new LambdaQueryWrapper<>();
            queryWrapper3.in(AutoflowStepSubPerson::getSubFlowId, objectAttributeList1);
            List<AutoflowStepSubPerson> list2 = autoflowStepSubPersonDao.list(queryWrapper3);
            AutoflowStepSubPersons = (JSONArray) JSON.toJSON(list2);
        }
        XSSFWorkbook workbook = FlowExcelWriter.createFlowXls(tempFilePath + "FLOW_MODEL.xlsx", oneAutoflowMainJson, nextflow, autoflowSteplistjson, AutoflowStepPersons, AutoflowSubs, AutoflowStepSubs, AutoflowStepSubPersons, useridtousernamemap);
        return workbook;

    }
    public Map<String,AuthUser> getUserInfoByNameAccounts(Set<String> usernames) {

        if (usernames == null || usernames.size() == 0) {
            return new HashMap<>();
        }
        usernames.remove("");

        Set<String> realNames = new HashSet<>();
        Set<String> Accounts = new HashSet<>();
        for (String name:usernames ) {
            String[] split = name.split(":");
            realNames.add(split[0]);
            if(split.length>1)
            {
                Accounts.add(split[1]);
            }
        }
        //根据登录账号查询用户信息
        List<AuthUser> swanEntUserAccounts = authUserDao.list(new LambdaQueryWrapper<AuthUser>().in(AuthUser::getUsername,Accounts));
        Map<String, AuthUser> stringSwanEntUserAccountMap =swanEntUserAccounts.stream().collect(Collectors.toMap(AuthUser::getUsername,line->line)) ;

        //根据名字查账号
        LambdaQueryWrapper<AuthUser> wrapper = new LambdaQueryWrapper<>();
        wrapper.in(AuthUser::getName, realNames);
        List<AuthUser> list = authUserDao.list(wrapper);

        Map<String,AuthUser> reallist = new HashMap<>();
        StringBuilder error = new StringBuilder();
        for (String nameacc:usernames   ) {
            AuthUser realUser = getRealUser(nameacc, list, stringSwanEntUserAccountMap, error);
            reallist.put(nameacc,realUser);
        }

        String s = error.toString();
        if(StrUtil.isNotBlank(s))
        {
            throw new InfoException("环节处理人信息错误：" + s);
        }
        return reallist;
    }

    private AuthUser getRealUser(String usernameAccount,List<AuthUser> users,Map<String, AuthUser> accountMap,StringBuilder error){
        String[] usernameAccounts = usernameAccount.split(":");
        String username = usernameAccounts[0];
        Map<String, List<AuthUser>> usergroup =users.stream().collect(Collectors.groupingBy(AuthUser::getName));
        if(usernameAccounts.length==1) {
            List<AuthUser> list = usergroup.get(username);

            if(list==null || list.size()==0)
            {
                error.append("用户名未找到：");
                error.append(username);
                error.append(",");
                return null;
            }
            if(list.size()>1)
            {
                error.append("重名的用户 请使用(用户名:登录账号)形式确定用户：");
                error.append(username);
                error.append(",");
                return null;
            }
            return list.get(0);
        }
        else{
            String account = usernameAccounts[1];
            AuthUser swanEntUserAccount = accountMap.get(account);
            List<AuthUser> list = usergroup.get(username);
            for (AuthUser user:list ) {
                if(user.getId().equals(swanEntUserAccount.getId())) {
                    return user;
                }
            }
            error.append("用户名和登录账号不匹配 请您确认：");
            error.append(usernameAccount);
            error.append(",");
            return null;
        }


    }

    @Override
    public AutoFlowMainLinkVo getAutoFlowMainLink(Long flowId) {
        // 获取当前流程信息
        AutoflowMain currentFlow = autoflowMainDao.getById(flowId);
        A.isNotNull(currentFlow, "流程不存在");

        // 创建返回对象
        AutoFlowMainLinkVo autoFlowMainLinkVo = new AutoFlowMainLinkVo();
        autoFlowMainLinkVo.setId(currentFlow.getId());
        autoFlowMainLinkVo.setName(currentFlow.getName());
        autoFlowMainLinkVo.setCode(currentFlow.getCode());

        // 获取当前流程所有环节
        List<AutoflowStep> currentSteps = autoflowStepDao.list(
                new LambdaQueryWrapper<AutoflowStep>()
                        .eq(AutoflowStep::getFlowId, currentFlow.getId())
                        .orderByAsc(AutoflowStep::getStepNo)
        );
        if (CollectionUtils.isNotEmpty(currentSteps)) {
            List<AutoflowStepVo> stepVos = currentSteps.stream().map(step -> {
                AutoflowStepVo stepVo = new AutoflowStepVo();
                BeanUtil.copyProperties(step, stepVo);
                return stepVo;
            }).collect(Collectors.toList());
            autoFlowMainLinkVo.setStepList(stepVos);
        }

        // 获取后置流程信息
        if (StrUtil.isNotBlank(currentFlow.getNextFlowCode())) {
            AutoflowMain nextFlow = autoflowMainDao.getOne(
                    new LambdaQueryWrapper<AutoflowMain>()
                            .eq(AutoflowMain::getCode, currentFlow.getNextFlowCode())
            );
            if (nextFlow != null) {
                AutoFlowMainVo nextFlowVo = new AutoFlowMainVo();
                BeanUtil.copyProperties(nextFlow, nextFlowVo);

                List<AutoflowStep> nextFlowSteps = autoflowStepDao.list(
                        new LambdaQueryWrapper<AutoflowStep>()
                                .eq(AutoflowStep::getFlowId, nextFlow.getId())
                                .orderByAsc(AutoflowStep::getStepNo)
                );
                if (CollectionUtils.isNotEmpty(nextFlowSteps)) {
                    List<AutoflowStepVo> nextStepVos = nextFlowSteps.stream().map(step -> {
                        AutoflowStepVo stepVo = new AutoflowStepVo();
                        BeanUtil.copyProperties(step, stepVo);
                        return stepVo;
                    }).collect(Collectors.toList());
                    nextFlowVo.setStepList(nextStepVos);
                }
                autoFlowMainLinkVo.setNextAutoFlow(nextFlowVo);
            }
        }

        // 获取前置流程列表
        List<AutoflowMain> preFlows = autoflowMainDao.list(
                new LambdaQueryWrapper<AutoflowMain>()
                        .eq(AutoflowMain::getNextFlowCode, currentFlow.getCode())
        );
        if (CollectionUtils.isNotEmpty(preFlows)) {
            List<AutoFlowMainVo> preFlowVos = preFlows.stream().map(preFlow -> {
                AutoFlowMainVo preFlowVo = new AutoFlowMainVo();
                BeanUtil.copyProperties(preFlow, preFlowVo);

                List<AutoflowStep> preFlowSteps = autoflowStepDao.list(
                        new LambdaQueryWrapper<AutoflowStep>()
                                .eq(AutoflowStep::getFlowId, preFlow.getId())
                                .orderByAsc(AutoflowStep::getStepNo)
                );
                if (CollectionUtils.isNotEmpty(preFlowSteps)) {
                    List<AutoflowStepVo> preStepVos = preFlowSteps.stream().map(step -> {
                        AutoflowStepVo stepVo = new AutoflowStepVo();
                        BeanUtil.copyProperties(step, stepVo);
                        return stepVo;
                    }).collect(Collectors.toList());
                    preFlowVo.setStepList(preStepVos);
                }

                return preFlowVo;
            }).collect(Collectors.toList());
            autoFlowMainLinkVo.setPreAutoFlows(preFlowVos);
        }

        return autoFlowMainLinkVo;
    }

}
